/*
 * Copyright (c) 2021, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.core.image.impl;

import boofcv.struct.image.*;

import javax.annotation.Generated;
//CONCURRENT_INLINE import boofcv.concurrency.BoofConcurrency;

/**
 * <p>
 * Functions for converting between different primitive image types. Numerical values do not change or are closely approximated
 * in these functions.
 * </p>
 *
 * <p>
 * DO NOT MODIFY. This code was automatically generated by GenerateImplConvertImage.
 * <p>
 *
 * @author Peter Abeles
 */
@Generated("boofcv.core.image.impl.GenerateImplConvertImage")
@SuppressWarnings("Duplicates")
public class ImplConvertImage {

	public static void convert( GrayU8 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( InterleavedU8 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( GrayU8 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU8 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU8 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU8 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU8 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] & 0xFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] & 0xFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU8 input , Planar<GrayU8> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayU8 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayU8> input , InterleavedU8 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayU8 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayS8 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( InterleavedS8 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( GrayS8 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS8 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS8 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS8 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS8 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS8 input , Planar<GrayS8> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayS8 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayS8> input , InterleavedS8 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayS8 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayU16 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU16 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( InterleavedU16 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( GrayU16 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU16 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU16 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayU16 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] & 0xFFFF);
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] & 0xFFFF);
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedU16 input , Planar<GrayU16> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayU16 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayU16> input , InterleavedU16 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayU16 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayS16 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS16 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( InterleavedS16 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			System.arraycopy(input.data, 0, output.data, 0, N);
		}
	}

	public static void convert( GrayS16 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS16 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS16 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS16 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS16 input , Planar<GrayS16> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayS16 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayS16> input , InterleavedS16 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayS16 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayS32 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS32 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS32 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS32 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS32 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS32 input , Planar<GrayS32> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayS32 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayS32> input , InterleavedS32 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayS32 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayS64 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS64 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS64 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS64 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayS64 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedS64 input , Planar<GrayS64> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayS64 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayS64> input , InterleavedS64 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayS64 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayF32 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF32 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF32 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF32 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( long )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( long )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( long )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( long )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF32 input, GrayF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input, InterleavedF64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( double )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( double )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF32 input , Planar<GrayF32> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayF32 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayF32> input , InterleavedF32 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayF32 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( GrayF64 input, GrayI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input, InterleavedI8 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( byte )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( byte )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF64 input, GrayI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input, InterleavedI16 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( short )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( short )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF64 input, GrayS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input, InterleavedS32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( int )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( int )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF64 input, GrayS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( long )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( long )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input, InterleavedS64 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( long )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( long )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( GrayF64 input, GrayF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < input.width; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height;

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input, InterleavedF32 output ) {

		if (input.isSubimage() || output.isSubimage()) {
			final int N = input.width * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = input.getIndex(0, y);
				int indexDst = output.getIndex(0, y);

				for (int x = 0; x < N; x++) {
					output.data[indexDst++] = ( float )( input.data[indexSrc++] );
				}
			}
			//CONCURRENT_ABOVE });

		} else {
			final int N = input.width * input.height * input.getNumBands();

			//CONCURRENT_BELOW BoofConcurrency.loopBlocks(0,N,(i0,i1)->{
			int i0 = 0, i1 = N;
			for (int i = i0; i < i1; i++) {
				output.data[i] = ( float )( input.data[i] );
			}
			//CONCURRENT_INLINE });
		}
	}

	public static void convert( InterleavedF64 input , Planar<GrayF64> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayF64 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = input.data[indexSrc];
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convert( Planar<GrayF64> input , InterleavedF64 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayF64 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;
				
				while( indexSrc != end ) { 
					output.data[indexDst] = band.data[indexSrc++];
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convertU8F32( InterleavedU8 input , Planar<GrayF32> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayF32 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = (input.data[indexSrc]& 0xFF);
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convertF32U8( InterleavedF32 input , Planar<GrayU8> output ) {

		final int numBands = input.numBands;
		for (int i = 0; i < numBands; i++) {
			GrayU8 band = output.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y*input.stride + input.startIndex + offset;
				int indexDst = y*output.stride + output.startIndex;
				int end = indexDst + input.width;
				while( indexDst != end ) {
					band.data[indexDst++] = (byte)(input.data[indexSrc]);
					indexSrc += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convertU8F32( Planar<GrayU8> input , InterleavedF32 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayU8 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;

				while( indexSrc != end ) { 
					output.data[indexDst] = (band.data[indexSrc++]& 0xFF);
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

	public static void convertF32U8( Planar<GrayF32> input , InterleavedU8 output ) {

		final int numBands = input.getNumBands();
		for (int i = 0; i < numBands; i++) {
			GrayF32 band = input.bands[i];
			final int offset = i;

			//CONCURRENT_BELOW BoofConcurrency.loopFor(0, input.height, y -> {
			for (int y = 0; y < input.height; y++) {
				int indexSrc = y * input.stride + input.startIndex;
				int indexDst = y * output.stride + output.startIndex + offset;
				int end = indexSrc + input.width;

				while( indexSrc != end ) { 
					output.data[indexDst] = (byte)(band.data[indexSrc++]);
					indexDst += numBands;
				}
			}
			//CONCURRENT_ABOVE });
		}
	}

}
